package com.googlecode.gwtbb.client.only.widget.basic;

import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.MouseListenerAdapter;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.Timer;

/**
 * @author Abraham Grief
 * @version $Id$
 * @since Feb 5, 2009
 */
public class TooltipMouseListener implements MouseListener {
	public static final int NO_DELAY = -1;
	private Widget widget;
	private int showDelayMillis = 200;
	private int hideDelayMillis = 200;
	private int leftOffset = 10;
	private int topOffset = 35;
	private Tooltip tooltip;
	private boolean inWidget;
	private boolean inTooltip;

	public TooltipMouseListener() {
	}

	public TooltipMouseListener(String text) {
		this(new Label(text));
	}

	public TooltipMouseListener(Widget widget) {
		this.widget = widget;
	}

	public Widget getWidget() {
		return widget;
	}

	public void setWidget(Widget widget) {
		this.widget = widget;
		if (tooltip != null)
			tooltip.setWidget(widget);
	}

	public int getHideDelayMillis() {
		return hideDelayMillis;
	}

	public void setHideDelayMillis(int hideDelayMillis) {
		this.hideDelayMillis = hideDelayMillis;
	}

	public int getShowDelayMillis() {
		return showDelayMillis;
	}

	public void setShowDelayMillis(int showDelayMillis) {
		this.showDelayMillis = showDelayMillis;
	}

	public int getLeftOffset() {
		return leftOffset;
	}

	public void setLeftOffset(int leftOffset) {
		this.leftOffset = leftOffset;
	}

	public int getTopOffset() {
		return topOffset;
	}

	public void setTopOffset(int topOffset) {
		this.topOffset = topOffset;
	}

	public void onMouseDown(Widget sender, int x, int y) {
	}

	public void onMouseEnter(Widget sender) {
		inWidget = true;
		show(sender);
	}

	public void onMouseLeave(Widget sender) {
		inWidget = false;
		hide(sender);
	}

	public void onMouseMove(Widget sender, int x, int y) {
	}

	public void onMouseUp(Widget sender, int x, int y) {
	}

	private void show(final Widget sender) {
		if (showDelayMillis == NO_DELAY) {
			doShow(sender);
		} else {
			Timer showTimer = new Timer() {
				public void run() {
					doShow(sender);
				}
			};
			showTimer.schedule(showDelayMillis);
		}
	}

	private void doShow(Widget sender) {
		if (inTooltip || inWidget) {
			if (tooltip == null) {
				tooltip = new Tooltip(widget);
				tooltip.addMouseListener(new MouseListenerAdapter() {
					@Override
					public void onMouseEnter(Widget sender) {
						inTooltip = true;
						show(sender);
					}

					@Override
					public void onMouseLeave(Widget sender) {
						inTooltip = false;

						// in some cases we don't re-enter the widget...
						// inWidget needs to be reset to true by the other onMouseEnter
						inWidget = false;
						hide(sender);
					}
				});
			}
			if (!tooltip.isShowing()) {
				tooltip.setPopupPosition(sender.getAbsoluteLeft() + leftOffset, sender.getAbsoluteTop() + topOffset);
				tooltip.show();
			}
		} else
			doHide(sender);
	}

	private void hide(final Widget sender) {
		if (hideDelayMillis == NO_DELAY) {
			doHide(sender);
		} else {
			Timer hideTimer = new Timer() {
				public void run() {
					doHide(sender);
				}
			};
			hideTimer.schedule(hideDelayMillis);
		}
	}

	private void doHide(Widget sender) {
		if (!inTooltip && !inWidget) {
			if (tooltip != null) {
				if (tooltip.isShowing())
					tooltip.hide();
			}
		} else
			doShow(sender);
	}
}
